﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using BusinessObjects;
using Microsoft.Practices.Composite.Events;
using YourWorld.Common.Infrastucture.Events;

namespace MainGameModule
{
    public class KidControl : Control
    {
        public static readonly DependencyProperty FramesPerSecondProperty = DependencyProperty.Register( "FramesPerSecond", typeof( double ), typeof( KidControl ), null );
        public static readonly DependencyProperty CountOfImagesProperty = DependencyProperty.Register( "CountOfImages", typeof( int ), typeof( KidControl ), null );
        public static readonly DependencyProperty DirectionProperty = DependencyProperty.Register( "Direction", typeof( MoveDirection ), typeof( KidControl ), new PropertyMetadata( OnDirectionPropertyChanged ) );
        public static readonly DependencyProperty IsMovingProperty = DependencyProperty.Register( "IsMoving", typeof( bool ), typeof( KidControl ), new PropertyMetadata( OnIsPausedPropertyChanged ) );
        public static readonly DependencyProperty PlayerProperty = DependencyProperty.Register( "Player", typeof( Player ), typeof( KidControl ), null );

        private Image image;
        private StackPanel playerHeader;
        private TextBlock playerNameTb;
        private Image connectImg;
        private Storyboard headerFade;
        private Grid kidGrid;

        private double averageInterval;
        private long lastTick = DateTime.Now.Ticks;
        private long lastlyActive = DateTime.Now.Ticks;
        private int currentImg = 0;

        private double x;
        private double y;

        public KidControl()
        {
            this.DefaultStyleKey = typeof( KidControl );
        }

        public Player Player
        {
            get { return ( Player )GetValue( PlayerProperty ); }
            set { SetValue( PlayerProperty, value ); }
        }

        public bool IsMoving
        {
            get { return ( bool )GetValue( IsMovingProperty ); }
            set { SetValue( IsMovingProperty, value ); }
        }

        public MoveDirection Direction
        {
            get { return ( MoveDirection )GetValue( DirectionProperty ); }
            set { SetValue( DirectionProperty, value ); }
        }

        public double FramesPerSecond
        {
            get { return ( double )GetValue( FramesPerSecondProperty ); }
            set { SetValue( FramesPerSecondProperty, value ); }
        }

        public int CountOfImages
        {
            get { return ( int )GetValue( CountOfImagesProperty ); }
            set { SetValue( CountOfImagesProperty, value ); }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            CompositionTarget.Rendering -= new EventHandler( CompositionTarget_Rendering );

            this.image = this.GetTemplateChild( "kidImage" ) as Image;
            this.playerHeader = this.GetTemplateChild( "playerHaader" ) as StackPanel;
            this.playerNameTb = this.GetTemplateChild( "nameField" ) as TextBlock;
            this.connectImg = this.GetTemplateChild( "connectImage" ) as Image;
            this.kidGrid = this.GetTemplateChild( "kidGrid" ) as Grid;

            this.x = this.Player.X;
            this.y = this.Player.Y;

            this.playerNameTb.Text = this.Player.Name;
            this.connectImg.MouseLeftButtonUp += new MouseButtonEventHandler( connectImg_MouseLeftButtonDown );

            this.averageInterval = TimeSpan.TicksPerSecond / this.FramesPerSecond;

            CompositionTarget.Rendering += new EventHandler( CompositionTarget_Rendering );

            this.kidGrid.MouseEnter += new MouseEventHandler( image_MouseEnter );
            this.kidGrid.MouseLeave += new MouseEventHandler( image_MouseLeave );
        }

        private void connectImg_MouseLeftButtonDown( object sender, MouseButtonEventArgs e )
        {
            EventService.Aggregator.GetEvent<ConnectToPlayerEvent>().Publish( this.Player.Id );
        }

        private void image_MouseLeave( object sender, MouseEventArgs e )
        {
            this.headerFade = new Storyboard();

            DoubleAnimation opcityAnim = new DoubleAnimation()
            {
                From = 1,
                To = 0,
                Duration = new Duration( TimeSpan.FromSeconds( 3 ) )
            };

            PropertyPath targetProperty = new PropertyPath( StackPanel.OpacityProperty );
            Storyboard.SetTargetProperty( opcityAnim, targetProperty );
            Storyboard.SetTarget( opcityAnim, this.playerHeader );

            headerFade.Children.Add( opcityAnim );
            this.headerFade.Begin();
        }

        private void image_MouseEnter( object sender, MouseEventArgs e )
        {
            if ( this.headerFade != null )
                this.headerFade.Stop();

            this.playerHeader.Opacity = 1;
        }

        private void CompositionTarget_Rendering( object sender, EventArgs e )
        {
            long now = DateTime.Now.Ticks;
            if ( now - this.lastTick < this.averageInterval )
                return;

            if ( this.x != this.Player.X || this.y != this.Player.Y )
            {
                //Change the direction
                if ( this.x < this.Player.X )
                    this.Direction = MoveDirection.Right;
                else if ( this.x > this.Player.X )
                    this.Direction = MoveDirection.Left;
                else if ( this.y < this.Player.Y )
                    this.Direction = MoveDirection.Up;
                else if ( this.y > this.Player.Y )
                    this.Direction = MoveDirection.Down;

                this.x = this.Player.X;
                this.y = this.Player.Y;
                this.lastlyActive = now;
                this.IsMoving = true;
            }
            else if ( now - this.lastlyActive > 1000 )
                this.IsMoving = false;

            if ( this.currentImg == this.CountOfImages )
                this.currentImg = 0;

            this.image.Source = new BitmapImage( new Uri( this.GetNexImageName( this.currentImg ), UriKind.RelativeOrAbsolute ) );

            if ( this.IsMoving == false && ( this.currentImg == 0 || this.currentImg == this.CountOfImages / 2 ) )
                return;

            this.lastTick = now;
            this.currentImg++;
        }

        private string GetNexImageName( int index )
        {
            string playerDir = ( ( CharacterTypes )this.Player.KidControlId ).ToString();

            return String.Format( "/MainGameModule;component/Images/{0}/{1}/kid000{2}.png",
                playerDir, this.Direction.ToString().ToLower(), index );
        }

        private static void OnDirectionPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
        {
            KidControl control = d as KidControl;
            control.currentImg = 0;
        }

        private static void OnIsPausedPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
        {

        }
    }
}
